Skip to content

Refactor to instanceof pattern variable#2017

Closed
arefbehboudi wants to merge 2 commits intospring-projects:mainfrom
arefbehboudi:patch-1
Closed

Refactor to instanceof pattern variable#2017
arefbehboudi wants to merge 2 commits intospring-projects:mainfrom
arefbehboudi:patch-1

Conversation

@arefbehboudi
Copy link
Copy Markdown

In some of our cases, we are currently using the traditional instanceof checks followed by explicit type casting. With the introduction of Pattern Matching in recent Java versions, we can refactor these checks to make the code more concise and readable.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jan 9, 2025
@mikereiche
Copy link
Copy Markdown
Contributor

mikereiche commented Jan 9, 2025

@arefbehboudi

Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

Also -
Please create an issue.
And the comment of the commit must end with ...

<newline>
Closes #<issue>.

@arefbehboudi
Copy link
Copy Markdown
Author

I signed https://cla.pivotal.io/sign/spring?repositoryId=spring-projects/spring-data-couchbase&pullRequestId=2017.

But how can I change the commit message after the push?

@mikereiche
Copy link
Copy Markdown
Contributor

git commit --amend

and then

git push -f ...

@arefbehboudi
Copy link
Copy Markdown
Author

Thank you!
I updated it.

schauder and others added 2 commits January 25, 2025 18:53
The constructor for DefaultTransaction now requires a name and `nested` flag.

Closes spring-projects#2016

Signed-off-by: arefbehboudi <behboodiaref@gmail.com>
Closes spring-projects#2018

Signed-off-by: arefbehboudi <behboodiaref@gmail.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors multiple instanceof checks across Spring Data Couchbase to use Java’s pattern matching for instanceof, reducing explicit casts and improving readability in query, conversion, and reactive operation code paths.

Changes:

  • Replaced instanceof + cast patterns with instanceof Type var across query building, mapping/conversion, and reactive operation support classes.
  • Updated a ternary instanceof branch in reactive query execution to bind the pattern variable.
  • Modified CouchbaseTransactionStatus to call a different DefaultTransactionStatus superclass constructor (adds additional arguments).

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/main/java/org/springframework/data/couchbase/transaction/CouchbaseTransactionStatus.java Changes superclass constructor invocation (beyond instanceof refactor).
src/main/java/org/springframework/data/couchbase/core/query/StringQuery.java Uses pattern variables for JsonArray parameter handling.
src/main/java/org/springframework/data/couchbase/core/query/QueryCriteria.java Uses pattern variables for JsonArray/List in in(...) handling.
src/main/java/org/springframework/data/couchbase/core/query/OptionsBuilder.java Uses pattern variables for query/tx parameter types.
src/main/java/org/springframework/data/couchbase/core/query/N1QLExpression.java Uses pattern variable when building paths from N1QLExpression components.
src/main/java/org/springframework/data/couchbase/core/query/Meta.java Uses pattern variables for String blank checks in meta setters.
src/main/java/org/springframework/data/couchbase/core/mapping/CouchbaseList.java Uses pattern variables when computing recursive size.
src/main/java/org/springframework/data/couchbase/core/index/CouchbasePersistentEntityIndexCreator.java Uses pattern variable for IndexDefinitionHolder selection.
src/main/java/org/springframework/data/couchbase/core/convert/translation/JacksonTranslationService.java Uses pattern variable for recursive document encoding.
src/main/java/org/springframework/data/couchbase/core/convert/MappingCouchbaseConverter.java Uses pattern variables in document/list reads, string conversion, and classloader-aware handling.
src/main/java/org/springframework/data/couchbase/core/convert/DateConverters.java Uses pattern variables for Number/String date conversion sources.
src/main/java/org/springframework/data/couchbase/core/ReactiveUpsertByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveReplaceByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveRemoveByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveRangeScanOperationSupport.java Uses pattern variables for runtime exception conversion in range scans.
src/main/java/org/springframework/data/couchbase/core/ReactiveMutateInByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveInsertByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveFindFromReplicasByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveFindByQueryOperationSupport.java Uses pattern variables for runtime exception conversion and result type branching.
src/main/java/org/springframework/data/couchbase/core/ReactiveFindByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/ReactiveFindByAnalyticsOperationSupport.java Uses pattern variables for runtime exception conversion in analytics queries.
src/main/java/org/springframework/data/couchbase/core/ReactiveExistsByIdOperationSupport.java Uses pattern variable for runtime exception conversion.
src/main/java/org/springframework/data/couchbase/core/CouchbaseTemplate.java Uses pattern variables for mapping context / application context checks.
src/main/java/org/springframework/data/couchbase/core/CouchbaseExceptionTranslator.java Uses pattern variable for TransactionOperationFailedException translation.
src/main/java/org/springframework/data/couchbase/core/AbstractTemplateSupport.java Uses pattern variable for CAS extraction from Number.
Comments suppressed due to low confidence (3)

src/main/java/org/springframework/data/couchbase/core/query/Meta.java:90

  • setValue claims to remove entries when value is null/blank, but after removing it unconditionally calls put(...) with the same (null/blank) value. This makes the removal ineffective and contradicts the method’s Javadoc; consider returning early after remove(...) or using an else before put(...).
		if (value == null || (value instanceof String str && !StringUtils.hasText(str))) {
			this.values.remove(MetaKey.valueOf(key));
		}
		this.values.put(MetaKey.valueOf(key), value);
	}

src/main/java/org/springframework/data/couchbase/core/query/Meta.java:98

  • Same issue as above: when value is null/blank the code removes the key but then immediately puts the (null/blank) value back into the map. Use early return or else so null/blank values actually remove the entry.
		if (value == null || (value instanceof String str && !StringUtils.hasText(str))) {
			this.values.remove(key);
		}
		this.values.put(key, value);
	}

src/main/java/org/springframework/data/couchbase/core/query/Meta.java:106

  • Same remove-then-put behavior here means null/blank values are still stored in values despite the intent to remove them. Consider restructuring this block so put(...) only happens when the value is non-null and (for Strings) non-blank.
		if (value == null || (value instanceof String str && !StringUtils.hasText(str))) {
			this.values.remove(key);
		}
		this.values.put(key, value);
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

CouchbaseMappingContext cmc = (CouchbaseMappingContext) mappingContext;
if (cmc.isAutoIndexCreation()) {
if (mappingContext instanceof CouchbaseMappingContext cmc) {
if (cmc.isAutoIndexCreation()) {
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation for the nested if uses spaces and is misaligned with the file’s tab-based indentation, which can cause noisy diffs and may violate formatting rules. Please reformat to match the surrounding indentation style.

Suggested change
if (cmc.isAutoIndexCreation()) {
if (cmc.isAutoIndexCreation()) {

Copilot uses AI. Check for mistakes.
Comment on lines 136 to 141
Object value = optsJson.get("args");
if(value instanceof JsonObject){
txOptions.parameters((JsonObject)value);
}else if(value instanceof JsonArray) {
txOptions.parameters((JsonArray) value);
if(value instanceof JsonObject jsonObject){
txOptions.parameters(jsonObject);
}else if(value instanceof JsonArray jsonArray) {
txOptions.parameters(jsonArray);
} else if(value != null) {
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated if/else if conditions here are missing spaces (if(value ...){, }else if(...){). Reformat to the consistent style used elsewhere in the file (if (value ...) {, } else if (...) {).

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +50
public CouchbaseTransactionStatus(Object transaction, boolean newTransaction, boolean newSynchronization, boolean readOnly, boolean debug, Object suspendedResources) {
super(null,
transaction,
newTransaction,
newSynchronization,
false,
readOnly,
debug,
suspendedResources);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change goes beyond an instanceof pattern refactor: it switches to a different DefaultTransactionStatus superclass constructor and passes null / false as additional arguments. Please confirm the targeted Spring DefaultTransactionStatus signature and document why these values are correct here (and update the PR description accordingly), since an argument-order mismatch could silently create a status with a null transaction.

Copilot uses AI. Check for mistakes.
if (context instanceof ConfigurableApplicationContext configurableApplicationContext && indexCreator != null) {
configurableApplicationContext.addApplicationListener(indexCreator);
if (mappingContext instanceof CouchbaseMappingContext cmc) {
cmc.setIndexCreator(indexCreator);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmc.setIndexCreator(indexCreator); is indented with spaces and doesn’t align with the surrounding block indentation. Reformat to match the file’s indentation style to avoid formatting-only diffs and potential checkstyle issues.

Suggested change
cmc.setIndexCreator(indexCreator);
cmc.setIndexCreator(indexCreator);

Copilot uses AI. Check for mistakes.
options.parameters((JsonObject) query.getParameters());
if (query.getParameters() instanceof JsonArray jsonArray && !jsonArray.isEmpty()) {
options.parameters(jsonArray);
} else if( query.getParameters() instanceof JsonObject jsonObject && !jsonObject.isEmpty()){
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spacing in the updated else if condition is inconsistent (else if( query...){). Since this hunk is already being modified, please normalize it to match the surrounding style (else if (query... && ...) {).

Suggested change
} else if( query.getParameters() instanceof JsonObject jsonObject && !jsonObject.isEmpty()){
} else if (query.getParameters() instanceof JsonObject jsonObject && !jsonObject.isEmpty()) {

Copilot uses AI. Check for mistakes.
Comment on lines +457 to 462
} else if (o[0] instanceof JsonArray jsonArray) {
value[0] = jsonArray.toList().toArray();
} else if (o[0] instanceof List list) {
List l = list;
value[0] = l.toArray();
}
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new JsonArray branch has inconsistent indentation (spaces vs tabs) compared to the surrounding code, and the List branch introduces an unnecessary temporary variable (List l = list). Align indentation and simplify to value[0] = list.toArray() (optionally with List<?> to avoid raw types).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants